/*
 * ImageAnalyzer.cpp
 *
 *  Created on: 10/09/2011
 *      Author: solnox
 */

#include "ImageAnalyzer.h"
using namespace cv;
using namespace std;
ImageAnalyzer::ImageAnalyzer() {
	fd_ = FeatureDetector::create("SURF");
	max_distance_ = 0.2;

}

ImageAnalyzer::~ImageAnalyzer() {
	fd_.delete_obj();
}


void ImageAnalyzer::detectKeyPoints( const Mat& image, vector<KeyPoint>& keypoints )
{
	fd_->detect(image,keypoints);
}

void ImageAnalyzer::computeDescriptors( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors )
{
	surf_.compute(image,keypoints,descriptors);
}


void  ImageAnalyzer::match(const AnalyzedImage & img1, const AnalyzedImage & img2, std::vector<cv::DMatch>& matches)
{

	crossCheckMatch(img1.desc,img2.desc,matches,max_distance_);
}

void ImageAnalyzer::crossCheckMatch( const cv::Mat& desc1, const cv::Mat& desc2,
		std::vector<cv::DMatch>& common_matches, float maxDistance)
{
	vector<DMatch> single_matches;
	vector<DMatch> single_reverse_matches;
	vector< vector<DMatch> > matches;
	vector< vector<DMatch> > reverseMatches;

	desc_matcher_.radiusMatch(desc1, desc2, matches, maxDistance);
	desc_matcher_.radiusMatch(desc2, desc1, reverseMatches, maxDistance);



	for(size_t k = 0; k < matches.size(); k++)
	{
		vector<DMatch> point_matches = matches.at(k);

		if(point_matches.size() > 0)
		{
			single_matches.push_back(point_matches.at(0));
		}
	}

	for(size_t k = 0; k < reverseMatches.size(); k++)
	{
		vector<DMatch> point_matches = reverseMatches.at(k);

		if(point_matches.size() > 0)
		{
			single_reverse_matches.push_back(point_matches.at(0));
		}
	}

	//cout << "    single matches         = " << single_matches.size() << endl;
	//cout << "    single reverse matches = " << single_reverse_matches.size() << endl;
	/*
	if ( single_matches.size() > cap )
	{
		std::nth_element(single_matches.begin(), single_matches.begin()+(cap-1), single_matches.end());
		single_matches.erase(single_matches.begin()+cap, single_matches.end());
	}

	if ( single_reverse_matches.size() > cap )
	{
		std::nth_element(single_reverse_matches.begin(), single_reverse_matches.begin()+(cap-1), single_reverse_matches.end());
		single_reverse_matches.erase(single_reverse_matches.begin()+cap, single_reverse_matches.end());
	}*/

	// getting common matches

	for(size_t k=0; k < single_matches.size(); k++)
	{
		for(size_t m=0; m < single_reverse_matches.size(); m++)
		{
			if ( single_matches[k].queryIdx == single_reverse_matches[m].trainIdx
					&& single_matches[k].trainIdx == single_reverse_matches[m].queryIdx)
			{
				common_matches.push_back(single_matches[k]);
			}
		}
	}

	//cout << "    common matches         = " << common_matches.size() << endl;
}

void ImageAnalyzer::getSingleMatches(vector<vector<DMatch> > & matches1to2 ,vector<DMatch> & single_matches1to2)
{
	for(int i = 0; i < (int)matches1to2.size(); i++)
	{
		vector<DMatch> point_matches = matches1to2.at(i);
		if(point_matches.size() > 0)
		{
			single_matches1to2.push_back(point_matches.at(0));
		}
	}

}

void ImageAnalyzer::getSingleReversedMatches(vector<vector<DMatch> > & matches2to1 ,vector<DMatch> & single_matches1to2)
{
	for(int i = 0; i < (int)matches2to1.size(); i++)
	{
		vector<DMatch> point_matches = matches2to1.at(i);
		if(point_matches.size() > 0)
		{
			DMatch match2to1 = point_matches.at(0);
			DMatch match1to2 = match2to1;
			match1to2.queryIdx = match2to1.trainIdx;
			match1to2.trainIdx =  match2to1.queryIdx;
			single_matches1to2.push_back(match1to2);
		}
	}

}
